package instruction

import (
	"fmt"
	"log"
)

func newInstruction(op byte) Instruction {
	log.Default().Printf("Parse OPCODE: 0x%02x", op)
	switch op {
	case 0x00:
		return &Noop{}
	case 0x01:
		return &A_const_NULL{}
	case 0x02:
		return &I_const_M1{}
	case 0x03:
		return &I_const_0{}
	case 0x04:
		return &I_const_1{}
	case 0x05:
		return &I_const_2{}
	case 0x06:
		return &I_const_3{}
	case 0x07:
		return &I_const_4{}
	case 0x08:
		return &I_const_5{}
	case 0x09:
		return &L_const_0{}
	case 0x0A:
		return &L_const_1{}
	case 0x0B:
		return &F_const_0{}
	case 0x0C:
		return &F_const_1{}
	case 0x0D:
		return &F_const_2{}
	case 0x0E:
		return &D_const_0{}
	case 0x0F:
		return &D_const_1{}
	case 0x10:
		return &B_i_push{}
	case 0x11:
		return &S_i_push{}
	case 0x12:
		return &LDC{}
	case 0x13:
		return &LDC_W{}
	case 0x14:
		return &LDC_2_W{}
	case 0x15:
		return &ILoad{}
	case 0x16:
		return &LLoad{}
	case 0x17:
		return &FLoad{}
	case 0x18:
		return &DLoad{}
	case 0x19:
		return &ALoad{}
	case 0x1A:
		return &ILoad0{}
	case 0x1B:
		return &ILoad1{}
	case 0x1C:
		return &ILoad2{}
	case 0x1D:
		return &ILoad3{}
	case 0x1E:
		return &LLoad0{}
	case 0x1F:
		return &LLoad1{}
	case 0x20:
		return &LLoad2{}
	case 0x21:
		return &LLoad3{}
	case 0x22:
		return &FLoad0{}
	case 0x23:
		return &FLoad1{}
	case 0x24:
		return &FLoad2{}
	case 0x25:
		return &FLoad3{}
	case 0x26:
		return &DLoad0{}
	case 0x27:
		return &DLoad1{}
	case 0x28:
		return &DLoad2{}
	case 0x29:
		return &DLoad3{}
	case 0x2A:
		return &ALoad0{}
	case 0x2B:
		return &ALoad1{}
	case 0x2C:
		return &ALoad2{}
	case 0x2D:
		return &ALoad3{}
	case 0x2E:
		return &IALoad{}
	case 0x2F:
		return &LALoad{}
	case 0x30:
		return &FALoad{}
	case 0x31:
		return &DALoad{}
	case 0x32:
		return &AALoad{}
	case 0x33:
		return &BALoad{}
	case 0x34:
		return &CALoad{}
	case 0x35:
		return &SALoad{}
	case 0x36:
		return &IStore{}
	case 0x37:
		return &LStore{}
	case 0x38:
		return &FStore{}
	case 0x39:
		return &DStore{}
	case 0x3A:
		return &AStore{}
	case 0x3B:
		return &IStore0{}
	case 0x3C:
		return &IStore1{}
	case 0x3D:
		return &IStore2{}
	case 0x3E:
		return &IStore3{}
	case 0x3F:
		return &LStore0{}
	case 0x40:
		return &LStore1{}
	case 0x41:
		return &LStore2{}
	case 0x42:
		return &LStore3{}
	case 0x43:
		return &FStore0{}
	case 0x44:
		return &FStore1{}
	case 0x45:
		return &FStore2{}
	case 0x46:
		return &FStore3{}
	case 0x47:
		return &DStore0{}
	case 0x48:
		return &FStore1{}
	case 0x49:
		return &FStore2{}
	case 0x4A:
		return &FStore3{}
	case 0x4B:
		return &AStore0{}
	case 0x4C:
		return &AStore1{}
	case 0x4D:
		return &AStore2{}
	case 0x4E:
		return &AStore3{}
	case 0x4F:
		return &IAStore{}
	case 0x50:
		return &LAStore{}
	case 0x51:
		return &FAStore{}
	case 0x52:
		return &DAStore{}
	case 0x53:
		return &AAStore{}
	case 0x54:
		return &BAStore{}
	case 0x55:
		return &CAStore{}
	case 0x56:
		return &SAStore{}
	case 0x57:
		return &POP{}
	case 0x58:
		return &POP2{}
	case 0x59:
		return &DUP{}
	case 0x60:
		return &IADD{}
	case 0x61:
		return &LADD{}
	case 0x62:
		return &FADD{}
	case 0x63:
		return &DADD{}
	case 0x64:
		return &ISub{}
	case 0x65:
		return &LSub{}
	case 0x66:
		return &FSub{}
	case 0x67:
		return &DSub{}
	case 0x78:
		return &ISHL{}
	case 0x79:
		return &LSHL{}
	case 0x7A:
		return &ISHR{}
	case 0x7B:
		return &LSHR{}
	case 0x7C:
		return &IUSHR{}
	case 0x7D:
		return &LUSHR{}
	case 0x7E:
		return &IAND{}
	case 0x7F:
		return &LAND{}
	case 0x80:
		return &IOR{}
	case 0x81:
		return &LOR{}
	case 0x82:
		return &IXOR{}
	case 0x83:
		return &LXOR{}
	case 0x84:
		return &IINC{}
	case 0x85:
		return &I2L{}
	case 0x86:
		return &I2F{}
	case 0x87:
		return &I2D{}
	case 0x88:
		return &L2I{}
	case 0x89:
		return &L2F{}
	case 0x8A:
		return &L2D{}
	case 0x8B:
		return &F2I{}
	case 0x8C:
		return &F2L{}
	case 0x8D:
		return &F2D{}
	case 0x8E:
		return &D2I{}
	case 0x8F:
		return &D2L{}
	case 0x90:
		return &D2F{}
	case 0x91:
		return &I2B{}
	case 0x92:
		return &I2C{}
	case 0x93:
		return &I2S{}
	case 0x94:
		return &LCMP{}
	case 0x95:
		return &FCmpL{}
	case 0x96:
		return &FCmpG{}
	case 0x97:
		return &DCmpL{}
	case 0x98:
		return &DCmpG{}
	case 0x99:
		return &IFEQ{}
	case 0x9A:
		return &IFNE{}
	case 0x9B:
		return &IFLT{}
	case 0x9C:
		return &IFGE{}
	case 0x9D:
		return &IFGT{}
	case 0x9E:
		return &IFLE{}
	case 0x9F:
		return &IFICMPEQ{}
	case 0xA0:
		return &IFICMPNE{}
	case 0xA1:
		return &IFICMPLT{}
	case 0xA2:
		return &IFICMPGE{}
	case 0xA3:
		return &IFICMPGT{}
	case 0xA4:
		return &IFICMPLE{}
	case 0xA5:
		return &IFACMPEQ{}
	case 0xA6:
		return &IFACMPNE{}
	case 0xA7:
		return &GOTO{}
		// 0xA8 JSR
		// 0xA9 RET
	case 0xAA:
		return &TableSwitch{}
	case 0xAB:
		return &LookupSwitch{}
	case 0xAC:
		return &IReturn{}
	case 0xAD:
		return &LReturn{}
	case 0xAE:
		return &FReturn{}
	case 0xAF:
		return &DReturn{}
	case 0xB0:
		return &AReturn{}
	case 0xB1:
		return &Return{}
	case 0xB2:
		return &GetStatic{}
	case 0xB3:
		return &PutStatic{}
	case 0xB4:
		return &GetField{}
	case 0xB5:
		return &PutField{}
	case 0xB6:
		return &INVOKE_VIRTUAL{}
	case 0xB7:
		return &INVOKE_SPECIAL{}
	case 0xB8:
		return &INVOKE_STATIC{}
	case 0xB9:
		return &INVOKE_INTERFACE{}
	case 0xBB:
		return &New{}
	case 0xBC:
		return &NewArray{}
	case 0xBD:
		return &ANewArray{}
	case 0xBE:
		return &ArrayLength{}
	case 0xC0:
		return &CheckCast{}
	case 0xC1:
		return &InstanceOf{}
	case 0xC5:
		return &MultiANewArray{}
	case 0xC6:
		return &IFNULL{}
	case 0xC7:
		return &IFNONNULL{}
	default:
		panic(fmt.Sprintf("Not support OPCODE: 0x%02x", op))
	}
}
